import  _ from 'lodash'
export default class DesignViewGrid {
    TAB_INDEX = 10;
    ENTER_KEY = 13;
    LEFT_ARROW_KEY = 37;
    RIGHT_ARROW_KEY = 39;
    ESCAPE_KEY = 27;
    TAB_KEY = 9;
  constants = {
    SOURCE: 'sourceDrop',
    SINK: 'sinkDrop',
    STREAM: 'streamDrop',
    TABLE: 'tableDrop',
    WINDOW: 'windowDrop',
    TRIGGER: 'triggerDrop',
    AGGREGATION: 'aggregationDrop',
    FUNCTION: 'functionDrop',
    PROJECTION: 'projectionQueryDrop',
    FILTER: 'filterQueryDrop',
    JOIN: 'joinQueryDrop',
    WINDOW_QUERY: 'windowQueryDrop',
    FUNCTION_QUERY: 'functionQueryDrop',
    PATTERN: 'patternQueryDrop',
    SEQUENCE: 'sequenceQueryDrop',
    PARTITION: 'partitionDrop',
    PARTITION_CONNECTION_POINT: 'partition-connector-in-part',
    SELECTOR: 'selector',
    MULTI_SELECTOR: 'multi-selector',
    TYPE_CALL: "call",
    TYPE_CALL_RESPONSE: "call-response",
    TYPE_HTTP_RESPONSE: "http-response"
  };
  constructor(options){
    var errorMessage = 'unable to find design view grid container';

    this.options = options;
    this.rawExtensions = options.rawExtensions;
    this.configurationData = this.options.configurationData;
    this.container = this.options.container;
    this.application = this.options.application;

    //this.currentTabId = this.application.tabController.activeTab.cid;
    this.designViewContainer = null;//$('#design-container-' + this.currentTabId);
    this.toggleViewButton = null;//$('#toggle-view-button-' + this.currentTabId);
    this.designGridContainer = null;//$('#design-grid-container-' + this.currentTabId);
    this.selectedElements = [];
    this.selectedObjects = [];
  }



  addSelectedElements = function(element){
      this.selectedElements.push(element);
  };

  isSelectedElements = function(element){
      if (this.selectedElements.includes(element)){
          return true;
      } else{
          return false;
      }
  };

  getSelectedElement = function(){
      return this.selectedElements;
  };

  resetSelectedElement = function(){
      this.selectedElements = [];
  };

  removeFromSelectedElements = function(element){
      for (var i = 0; i < this.selectedElements.length; i++) {
          if (this.selectedElements[i] == element) {
              this.selectedElements.splice(i, 1);
          }
      }
  };

  render() {
      var self = this;

      // newAgentId --> newAgent ID (Dropped Element ID)
      this.newAgentId = "0";
      var dropElementsOpts = {};
      _.set(dropElementsOpts, 'container', self.container);
      _.set(dropElementsOpts, 'configurationData', self.configurationData);
      _.set(dropElementsOpts, 'application', self.application);

      _.set(dropElementsOpts, 'designGrid', self);


      // add text fields to display the siddhi app name and description
      var siddhiAppNameNodeId = self.currentTabId + '-siddhiAppNameId';
      var siddhiAppName = self.configurationData.getSiddhiAppConfig().getSiddhiAppName();
      console.info('siddhi文件名：'+siddhiAppName);
      var siddhiAppNameNode = "<div id='" + siddhiAppNameNodeId + "' " +
          "class='siddhi-app-name-node'>" + siddhiAppName + "</div>";
      var siddhiAppDescription = self.configurationData.getSiddhiAppConfig().getSiddhiAppDescription();
      var siddhiAppDescriptionNode = "<div id='siddhi-app-desc-node'>" + siddhiAppDescription + "</div>";




      _.forEach(self.configurationData.edgeList, function (edge) {
          var targetId;
          var sourceId;
          var paintStyle = {
              strokeWidth: 2,
              stroke: '#424242',
              outlineStroke: "transparent",
              outlineWidth: "3"
          };

          if (edge.getChildType() === 'PARTITION') {
              targetId = edge.getChildId();
              sourceId = edge.getParentId() + '-out';
          } else if (edge.getParentType() === 'PARTITION') {
              targetId = edge.getChildId() + '-in';
              sourceId = edge.getParentId();
          } else if (edge.getParentType() === 'SINK' && edge.getChildType() === 'SOURCE') {
              targetId = edge.getChildId() + '-in';
              sourceId = edge.getParentId() + '-out';
              paintStyle = {
                  strokeWidth: 2, stroke: "#424242", dashstyle: "2 3", outlineStroke: "transparent",
                  outlineWidth: "3"
              }
          } else {
              // check if the edge is originating from a fault stream. if so get the corresponding event stream
              // and draw the edge from the -err-out connector.
              if (edge.isFromFaultStream()) {
                  sourceId = edge.getParentId() + '-err-out';
                  paintStyle = {
                      strokeWidth: 2, stroke: "#FF0000", dashstyle: "2 3", outlineStroke: "transparent",
                      outlineWidth: "3"
                  };
              } else {
                  sourceId = edge.getParentId() + '-out';
              }
              targetId = edge.getChildId() + '-in';
          }

      });


      /*
      * In here we set a timeout because when drawing the graph jsplumb triggers a 'addMember' event (when adding
      * an element to the partition) an it takes some time to execute. So that we add a timeout and set the
      * isDesignViewContentChange to false.
      * */
      setTimeout(function () {
          // set the isDesignViewContentChanged to false
          self.configurationData.setIsDesignViewContentChanged(false);

          // set isStillDrawingGraph to false since the graph drawing is done
          self.configurationData.setIsStillDrawingGraph(false);
      }, 100);
  };


  handleSourceAnnotation(mouseTop, mouseLeft, isCodeToDesignMode, sourceName,
                                                          sourceId, sourceToolTip) {
      var self = this;
      var elementId;
      if (isCodeToDesignMode !== undefined && !isCodeToDesignMode) {
          elementId = self.getNewAgentId();
      } else if (isCodeToDesignMode !== undefined && isCodeToDesignMode) {
          if (sourceId !== undefined) {
              elementId = sourceId;
              self.generateNextNewAgentId();
          } else {
              console.log("sourceId parameter is undefined");
          }
      } else {
          console.log("isCodeToDesignMode parameter is undefined");
      }
      var newAgent = $('<div>').attr({
          'id': elementId,
          'tabindex': TAB_INDEX
      }).addClass(constants.SOURCE);
      if (isCodeToDesignMode) {
          newAgent.attr('title', sourceToolTip);
      }
      self.canvas.append(newAgent);
      // Drop the source element. Inside this a it generates the source definition form.
      self.dropElements.dropSource(newAgent, elementId, mouseTop, mouseLeft, isCodeToDesignMode, sourceName);
      self.configurationData.getSiddhiAppConfig()
          .setFinalElementCount(self.configurationData.getSiddhiAppConfig().getFinalElementCount() + 1);
      self.dropElements.registerElementEventListeners(newAgent);
      self.enableMultipleSelection();
  };

  handleSinkAnnotation(mouseTop, mouseLeft, isCodeToDesignMode, sinkName,
                                                        sinkId, sinkToolTip) {
      var self = this;
      var elementId;
      if (isCodeToDesignMode !== undefined && !isCodeToDesignMode) {
          elementId = self.getNewAgentId();
      } else if (isCodeToDesignMode !== undefined && isCodeToDesignMode) {
          if (sinkId !== undefined) {
              elementId = sinkId;
              self.generateNextNewAgentId();
          } else {
              console.log("sinkId parameter is undefined");
          }
      } else {
          console.log("isCodeToDesignMode parameter is undefined");
      }
      var newAgent = $('<div>').attr({
          'id': elementId,
          'tabindex': TAB_INDEX
      }).addClass(constants.SINK);
      if (isCodeToDesignMode) {
          newAgent.attr('title', sinkToolTip);
      }
      self.canvas.append(newAgent);
      // Drop the sink element. Inside this a it generates the sink definition form.
      self.dropElements.dropSink(newAgent, elementId, mouseTop, mouseLeft, isCodeToDesignMode, sinkName);
      self.configurationData.getSiddhiAppConfig()
          .setFinalElementCount(self.configurationData.getSiddhiAppConfig().getFinalElementCount() + 1);
      self.dropElements.registerElementEventListeners(newAgent);
      self.enableMultipleSelection();
  };

  handleStream(mouseTop, mouseLeft, isCodeToDesignMode, streamId, streamName,
                                                streamToolTip, stream) {
      var self = this;
      var elementId;
      if (isCodeToDesignMode !== undefined && !isCodeToDesignMode) {
          elementId = stream && stream.getId() ? stream.getId() : self.getNewAgentId();
      } else if (isCodeToDesignMode !== undefined && isCodeToDesignMode) {
          if (streamId !== undefined) {
              elementId = streamId;
              self.generateNextNewAgentId();
          } else {
              console.log("streamId parameter is undefined");
          }
      } else {
          console.log("isCodeToDesignMode parameter is undefined");
      }

      var newAgent = $('<div>').attr({
          'id': elementId,
          'tabindex': TAB_INDEX
      }).addClass(constants.STREAM);

      var inFaultStreamCreationPath = false;

      // If this is a fault stream, hide it
      if (stream && stream.isFaultStream()) {
          newAgent.hide();
          inFaultStreamCreationPath = true;
      }

      if (isCodeToDesignMode) {
          newAgent.attr('title', streamToolTip);
      }
      self.canvas.append(newAgent);
      // Drop the stream element. Inside this a it generates the stream definition form.
      self.dropElements.dropStream(newAgent, elementId, mouseTop, mouseLeft, isCodeToDesignMode,
          false, streamName, stream && stream.hasFaultStream(), inFaultStreamCreationPath);
      self.configurationData.getSiddhiAppConfig()
          .setFinalElementCount(self.configurationData.getSiddhiAppConfig().getFinalElementCount() + 1);
      self.dropElements.registerElementEventListeners(newAgent);
      self.enableMultipleSelection();
  };

  handleTable(mouseTop, mouseLeft, isCodeToDesignMode, tableId, tableName,
                                               tableToolTip) {
      var self = this;
      var elementId;
      if (isCodeToDesignMode !== undefined && !isCodeToDesignMode) {
          elementId = self.getNewAgentId();
      } else if (isCodeToDesignMode !== undefined && isCodeToDesignMode) {
          if (tableId !== undefined) {
              elementId = tableId;
              self.generateNextNewAgentId();
          } else {
              console.log("tableId parameter is undefined");
          }
      } else {
          console.log("isCodeToDesignMode parameter is undefined");
      }
      var newAgent = $('<div>').attr({
          'id': elementId,
          'tabindex': TAB_INDEX
      }).addClass(constants.TABLE);
      if (isCodeToDesignMode) {
          newAgent.attr('title', tableToolTip);
      }
      self.canvas.append(newAgent);
      // Drop the Table element. Inside this a it generates the table definition form.
      self.dropElements.dropTable(newAgent, elementId, mouseTop, mouseLeft, isCodeToDesignMode, tableName);
      self.configurationData.getSiddhiAppConfig()
          .setFinalElementCount(self.configurationData.getSiddhiAppConfig().getFinalElementCount() + 1);
      self.dropElements.registerElementEventListeners(newAgent);
      self.enableMultipleSelection();
  };

  handleWindow(mouseTop, mouseLeft, isCodeToDesignMode, windowId, windowName,
                                                windowToolTip) {
      var self = this;
      var elementId;
      if (isCodeToDesignMode !== undefined && !isCodeToDesignMode) {
          elementId = self.getNewAgentId();
      } else if (isCodeToDesignMode !== undefined && isCodeToDesignMode) {
          if (windowId !== undefined) {
              elementId = windowId;
              self.generateNextNewAgentId();
          } else {
              console.log("windowId parameter is undefined");
          }
      } else {
          console.log("isCodeToDesignMode parameter is undefined");
      }
      var newAgent = $('<div>').attr({
          'id': elementId,
          'tabindex': TAB_INDEX
      }).addClass(constants.WINDOW);
      if (isCodeToDesignMode) {
          newAgent.attr('title', windowToolTip);
      }
      self.canvas.append(newAgent);
      // Drop the Table element. Inside this a it generates the table definition form.
      self.dropElements.dropWindow(newAgent, elementId, mouseTop, mouseLeft, isCodeToDesignMode, windowName);
      self.configurationData.getSiddhiAppConfig()
          .setFinalElementCount(self.configurationData.getSiddhiAppConfig().getFinalElementCount() + 1);
      self.dropElements.registerElementEventListeners(newAgent);
      self.enableMultipleSelection();
  };

  handleTrigger(mouseTop, mouseLeft, isCodeToDesignMode, triggerId,
                                                 triggerName, triggerToolTip) {
      var self = this;
      var elementId;
      if (isCodeToDesignMode !== undefined && !isCodeToDesignMode) {
          elementId = self.getNewAgentId();
      } else if (isCodeToDesignMode !== undefined && isCodeToDesignMode) {
          if (triggerId !== undefined) {
              elementId = triggerId;
              self.generateNextNewAgentId();
          } else {
              console.log("triggerId parameter is undefined");
          }
      } else {
          console.log("isCodeToDesignMode parameter is undefined");
      }
      var newAgent = $('<div>').attr({
          'id': elementId,
          'tabindex': TAB_INDEX
      }).addClass(constants.TRIGGER);
      if (isCodeToDesignMode) {
          newAgent.attr('title', triggerToolTip);
      }
      self.canvas.append(newAgent);
      // Drop the Trigger element. Inside this a it generates the trigger definition form.
      self.dropElements.dropTrigger(newAgent, elementId, mouseTop, mouseLeft, isCodeToDesignMode, triggerName);
      self.configurationData.getSiddhiAppConfig()
          .setFinalElementCount(self.configurationData.getSiddhiAppConfig().getFinalElementCount() + 1);
      self.dropElements.registerElementEventListeners(newAgent);
      self.enableMultipleSelection();
  };

  handleAggregation(mouseTop, mouseLeft, isCodeToDesignMode, aggregationId,
                                                     aggregationName, aggregationToolTip) {
      var self = this;
      var elementId;
      if (isCodeToDesignMode !== undefined && !isCodeToDesignMode) {
          elementId = self.getNewAgentId();
      } else if (isCodeToDesignMode !== undefined && isCodeToDesignMode) {
          if (aggregationId !== undefined) {
              elementId = aggregationId;
              self.generateNextNewAgentId();
          } else {
              console.log("aggregationId parameter is undefined");
          }
      } else {
          console.log("isCodeToDesignMode parameter is undefined");
      }
      var newAgent = $('<div>').attr({
          'id': elementId,
          'tabindex': TAB_INDEX
      }).addClass(constants.AGGREGATION);
      if (isCodeToDesignMode) {
          newAgent.attr('title', aggregationToolTip);
      }
      self.canvas.append(newAgent);
      // Drop the Aggregation element. Inside this a it generates the aggregation definition form.
      self.dropElements.dropAggregation(newAgent, elementId, mouseTop, mouseLeft, isCodeToDesignMode,
          aggregationName);
      self.configurationData.getSiddhiAppConfig()
          .setFinalElementCount(self.configurationData.getSiddhiAppConfig().getFinalElementCount() + 1);
      self.dropElements.registerElementEventListeners(newAgent);
      self.enableMultipleSelection();
  };

  handleFunction(mouseTop, mouseLeft, isCodeToDesignMode, functionId,
                                                  functionName, functionToolTip) {
      var self = this;
      var elementId;
      if (isCodeToDesignMode !== undefined && !isCodeToDesignMode) {
          elementId = self.getNewAgentId();
      } else if (isCodeToDesignMode !== undefined && isCodeToDesignMode) {
          if (functionId !== undefined) {
              elementId = functionId;
              self.generateNextNewAgentId();
          } else {
              console.log("functionId parameter is undefined");
          }
      } else {
          console.log("isCodeToDesignMode parameter is undefined");
      }
      var newAgent = $('<div>').attr({
          'id': elementId,
          'tabindex': TAB_INDEX
      }).addClass(constants.FUNCTION);
      if (isCodeToDesignMode) {
          newAgent.attr('title', functionToolTip);
      }
      self.canvas.append(newAgent);
      // Drop the Function element. Inside this a it generates the function definition form.
      self.dropElements.dropFunction(newAgent, elementId, mouseTop, mouseLeft, isCodeToDesignMode, functionName);
      self.configurationData.getSiddhiAppConfig()
          .setFinalElementCount(self.configurationData.getSiddhiAppConfig().getFinalElementCount() + 1);
      self.dropElements.registerElementEventListeners(newAgent);
      self.enableMultipleSelection();
  };


  handleWindowFilterProjectionQuery(type, mouseTop, mouseLeft,
                                                                     isCodeToDesignMode, queryName, queryId,
                                                                     queryToolTip) {
      var self = this;
      var elementId;
      if (isCodeToDesignMode !== undefined && !isCodeToDesignMode) {
          elementId = self.getNewAgentId();
      } else if (isCodeToDesignMode !== undefined && isCodeToDesignMode) {
          if (queryId !== undefined) {
              elementId = queryId;
              self.generateNextNewAgentId();
          } else {
              console.log("queryId parameter is undefined");
          }
      } else {
          console.log("isCodeToDesignMode parameter is undefined");
      }
      var newAgent = $('<div>').attr({
          'id': elementId,
          'tabindex': TAB_INDEX
      }).addClass(type);
      if (isCodeToDesignMode) {
          newAgent.attr('title', queryToolTip);
      }
      self.canvas.append(newAgent);
      // Drop the element instantly since its projections will be set only when the user requires it
      self.dropElements.dropWindowFilterProjectionQuery(newAgent, elementId, type, mouseTop, mouseLeft, queryName,
          isCodeToDesignMode);
      self.configurationData.getSiddhiAppConfig()
          .setFinalElementCount(self.configurationData.getSiddhiAppConfig().getFinalElementCount() + 1);
      self.dropElements.registerElementEventListeners(newAgent);
      self.enableMultipleSelection();
  };

  handleJoinQuery(mouseTop, mouseLeft, isCodeToDesignMode, joinQueryName,
                                                   joinQueryId, joinQueryToolTip) {
      var self = this;
      var elementId;
      if (isCodeToDesignMode !== undefined && !isCodeToDesignMode) {
          elementId = self.getNewAgentId();
      } else if (isCodeToDesignMode !== undefined && isCodeToDesignMode) {
          if (joinQueryId !== undefined) {
              elementId = joinQueryId;
              self.generateNextNewAgentId();
          } else {
              console.log("queryId parameter is undefined");
          }
      } else {
          console.log("isCodeToDesignMode parameter is undefined");
      }
      var newAgent = $('<div>').attr({
          'id': elementId,
          'tabindex': TAB_INDEX
      }).addClass(constants.JOIN);
      if (isCodeToDesignMode) {
          newAgent.attr('title', joinQueryToolTip);
      }
      self.canvas.append(newAgent);
      // Drop the element instantly since its projections will be set only when the user requires it
      self.dropElements.dropJoinQuery(newAgent, elementId, mouseTop, mouseLeft, joinQueryName,
          isCodeToDesignMode);
      self.configurationData.getSiddhiAppConfig()
          .setFinalElementCount(self.configurationData.getSiddhiAppConfig().getFinalElementCount() + 1);
      self.dropElements.registerElementEventListeners(newAgent);
      self.enableMultipleSelection();
  };

  handlePatternQuery(mouseTop, mouseLeft, isCodeToDesignMode, patternQueryName,
                                                      patternQueryId, patternQueryToolTip) {
      var self = this;
      var elementId;
      if (isCodeToDesignMode !== undefined && !isCodeToDesignMode) {
          elementId = self.getNewAgentId();
      } else if (isCodeToDesignMode !== undefined && isCodeToDesignMode) {
          if (patternQueryId !== undefined) {
              elementId = patternQueryId;
              self.generateNextNewAgentId();
          } else {
              console.log("patternQueryId parameter is undefined");
          }
      } else {
          console.log("isCodeToDesignMode parameter is undefined");
      }
      var newAgent = $('<div>').attr({
          'id': elementId,
          'tabindex': TAB_INDEX
      }).addClass(constants.PATTERN);
      if (isCodeToDesignMode) {
          newAgent.attr('title', patternQueryToolTip);
      }
      self.canvas.append(newAgent);
      // Drop the element instantly since its projections will be set only when the user requires it
      self.dropElements.dropPatternQuery(newAgent, elementId, mouseTop, mouseLeft, isCodeToDesignMode,
          patternQueryName);
      self.configurationData.getSiddhiAppConfig()
          .setFinalElementCount(self.configurationData.getSiddhiAppConfig().getFinalElementCount() + 1);
      self.dropElements.registerElementEventListeners(newAgent);
      self.enableMultipleSelection();
  };

  handleSequenceQuery(mouseTop, mouseLeft, isCodeToDesignMode, sequenceQueryName,
                                                       sequenceQueryId, sequenceQueryToolTip) {
      var self = this;
      var elementId;
      if (isCodeToDesignMode !== undefined && !isCodeToDesignMode) {
          elementId = self.getNewAgentId();
      } else if (isCodeToDesignMode !== undefined && isCodeToDesignMode) {
          if (sequenceQueryId !== undefined) {
              elementId = sequenceQueryId;
              self.generateNextNewAgentId();
          } else {
              console.log("sequenceQueryId parameter is undefined");
          }
      } else {
          console.log("isCodeToDesignMode parameter is undefined");
      }
      var newAgent = $('<div>').attr({
          'id': elementId,
          'tabindex': TAB_INDEX
      }).addClass(constants.SEQUENCE);
      if (isCodeToDesignMode) {
          newAgent.attr('title', sequenceQueryToolTip);
      }
      self.canvas.append(newAgent);
      // Drop the element instantly since its projections will be set only when the user requires it
      self.dropElements.dropSequenceQuery(newAgent, elementId, mouseTop, mouseLeft, isCodeToDesignMode,
          sequenceQueryName);
      self.configurationData.getSiddhiAppConfig()
          .setFinalElementCount(self.configurationData.getSiddhiAppConfig().getFinalElementCount() + 1);
      self.dropElements.registerElementEventListeners(newAgent);
      self.enableMultipleSelection();
  };

  handlePartition(mouseTop, mouseLeft, isCodeToDesignMode, partitionId,
                                                   partitionToolTip) {
      var self = this;
      var elementId;
      if (isCodeToDesignMode !== undefined && !isCodeToDesignMode) {
          elementId = self.getNewAgentId();
      } else if (isCodeToDesignMode !== undefined && isCodeToDesignMode) {
          if (partitionId !== undefined) {
              elementId = partitionId;
              self.generateNextNewAgentId();
          } else {
              console.log("partitionId parameter is undefined");
          }
      } else {
          console.log("isCodeToDesignMode parameter is undefined");
      }
      var newAgent = $('<div>').attr({
          'id': elementId,
          'tabindex': TAB_INDEX
      }).addClass(constants.PARTITION);
      if (isCodeToDesignMode) {
          newAgent.attr('title', partitionToolTip);
      }
      self.canvas.append(newAgent);
      // Drop the element instantly since its projections will be set only when the user requires it
      self.dropElements.dropPartition(newAgent, elementId, mouseTop, mouseLeft, isCodeToDesignMode);
      self.configurationData.getSiddhiAppConfig()
          .setFinalElementCount(self.configurationData.getSiddhiAppConfig().getFinalElementCount() + 1);
      self.dropElements.registerElementEventListeners(newAgent);
      self.enableMultipleSelection();
  };

  generateNextNewAgentId() {
      var newId = parseInt(this.newAgentId) + 1;
      this.newAgentId = "" + newId + "";
      return this.currentTabId + "_element_" + this.newAgentId;
  };

  getNewAgentId() {
      var self = this;
      return self.generateNextNewAgentId();
  };

  /**
   * Generate tooltips for all the elements
   *
   * @param designViewJSON siddhiAppConfig
   */
  getTooltips(designViewJSON) {
      var self = this;
      var result = {};
      self.tooltipsURL = window.location.protocol + "//" + window.location.host + "/editor/tooltips";
      $.ajax({
          type: "POST",
          url: self.tooltipsURL,
          data: self.options.application.utils.base64EncodeUnicode(designViewJSON),
          async: false,
          success: function (response) {
              result = {status: "success", tooltipList: response};
          },
          error: function (error) {
              if (error.responseText) {
                  result = {status: "fail", errorMessage: error.responseText};
              } else {
                  result = {status: "fail", errorMessage: "Error Occurred while processing your request"};
              }
          }
      });
      return result;
  };
}
